package com.ygqh.baby.handler;

import com.ygqh.baby.ao.PromotionStatus;
import com.ygqh.baby.ao.PromotionType;
import com.ygqh.baby.ao.SalesPlatform;
import com.ygqh.baby.model.BmdismLadderModel;
import com.ygqh.baby.model.CarPromotionWrapper;
import com.ygqh.baby.model.ShoppingCarBasicData;
import com.ygqh.baby.model.YgPtSkuInfo;
import com.ygqh.baby.po.YgProductPack;
import com.ygqh.baby.po.YgPromotion;
import com.ygqh.baby.service.*;
import com.ygqh.baby.utils.PlatformUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 〈〉
 *
 * @author guohao
 * @date 2019/5/6 11:34
 * @since 1.0.0
 */
@Component
public class CarPromotionHandler {
    @Autowired
    private YgBmdismService ygBmdismService;
    @Autowired
    private YgProductPackV2Service ygProductPackV2Service;
    @Autowired
    private YgUserService ygUserService;
    @Autowired
    private YgShoppingCarService ygShoppingCarService;
    @Autowired
    private YgPromotionService ygPromotionService;
    @Autowired
    private YgProductActionGiftService ygProductActionGiftService;

    public List<ShoppingCarBasicData> getCarBasicDataList(Long userId, SalesPlatform salesPlatform, List<YgPtSkuInfo> skuList) {
        List<ShoppingCarBasicData> carBasicDataList;
        if (CollectionUtils.isNotEmpty(skuList)) {
            List<Long> skuIds = skuList.stream().map(YgPtSkuInfo::getSkuId).collect(Collectors.toList());
            carBasicDataList = ygShoppingCarService.findCarBasicDataListBySkuId(userId, PromotionType.GroupBuying, skuIds);
            resetQuantity(skuList, carBasicDataList);
        } else {
            carBasicDataList = ygShoppingCarService.findCarBasicDataList(userId, salesPlatform);
        }
        return carBasicDataList;

    }

    /**
     * 设置购物车数量
     *
     * @param skuList          购物车商品数量
     * @param carBasicDataList 购物车商品信息
     */
    private void resetQuantity(List<YgPtSkuInfo> skuList, List<ShoppingCarBasicData> carBasicDataList) {
        for (ShoppingCarBasicData data : carBasicDataList) {
            for (YgPtSkuInfo sku : skuList) {
                if (data.getSkuId().equals(sku.getSkuId())) {
                    data.setQuantity(sku.getQuantity());
                }
            }

        }
    }

    public List<CarPromotionWrapper> getCarListWithPromotion(List<ShoppingCarBasicData> carBasicDataList,
                                                             Boolean distribution, String platformNo) {
        Long userId = carBasicDataList.get(0).getUserId();

        Boolean newCustom = ygUserService.isNewCustom(userId, platformNo);
        Boolean vip = ygUserService.isVipNew(userId, platformNo);
        restRealSalesPrice(carBasicDataList, vip, distribution);
        carBasicDataList = sortByRealSalesPriceDesc(carBasicDataList);
        //设置促销标签
        List<CarPromotionWrapper> carPromotionWrapperList = setPromotionTag(carBasicDataList, newCustom, platformNo);
        //找出满足促销的 取消不满足的
        setMeetPromotionTag(carPromotionWrapperList, vip, newCustom, distribution);

        CarApportionPriceHandler.calculateEachCarDisPrice(carPromotionWrapperList, vip, newCustom, distribution);

        return carPromotionWrapperList;
    }


    private void restRealSalesPrice(List<ShoppingCarBasicData> carList, Boolean vip, Boolean distribution) {
        resetNewCustomPrice(carList);
        carList.forEach(car -> doSetRealSalesPrice(car, vip, distribution));
    }

    private void doSetRealSalesPrice(ShoppingCarBasicData car, boolean vip, boolean distribution) {
        if (PromotionType.GroupBuying.equals(car.getSalesType())) {
            car.setSalesPrice(car.getPromotionPrice());
            car.setRealSalesPrice(car.getPromotionPrice());
        } else if (PromotionType.JiaJiaGou.equals(car.getSalesType())) {
            car.setVipPrice(BigDecimal.ZERO);
            car.setSalesPrice(car.getPromotionPrice());
            car.setRealSalesPrice(car.getPromotionPrice());
        } else if (PromotionType.ManZeng.equals(car.getSalesType())) {
            car.setVipPrice(BigDecimal.ZERO);
            car.setRealSalesPrice(BigDecimal.ZERO);
            car.setSalesPrice(BigDecimal.ZERO);
        } else {
            car.setRealSalesPrice(car.getSalesPrice());
        }

        if (vip && car.getVipPrice() != null && car.getVipPrice().compareTo(BigDecimal.ZERO) > 0) {
            car.setRealSalesPrice(car.getVipPrice());
        }
        if (distribution && car.getDistributionPrice() != null && car.getDistributionPrice().compareTo(BigDecimal.ZERO) > 0) {
            car.setRealSalesPrice(car.getDistributionPrice());
        }

    }

    /**
     * 设置促销标记 (原则：一件商品只能享受一种促销手段)
     * 顺序标记  自选包->多买多折->新客专享
     * <p>
     * 1。新客价
     * 同一花色下，多个尺码只用一件商品参与新客价
     * 2.自选包与新客商品互斥
     * 商品即是自选包又是新客商品时，程序按自选包处理
     * 3.多买多折与新客互斥
     * 商品即是多买多折又是新客商品时，程序按多买多折处理
     * 4.多买多折、自选包 互斥
     *
     * @param carBasicDataList 购物车信息
     */
    private List<CarPromotionWrapper> setPromotionTag(List<ShoppingCarBasicData> carBasicDataList, Boolean isNewCustoms, String platformNo) {
        Long[] productIds = carBasicDataList.stream().map(ShoppingCarBasicData::getProductId)
                .toArray(Long[]::new);
        List<YgProductPack> packList = ygProductPackV2Service.findPackListByProductId(PromotionStatus.Running, productIds);
        List<CarPromotionWrapper> carPromotionWrapperList = new ArrayList<>(carBasicDataList.size());
        carBasicDataList.forEach(item -> {
            //自选包
            CarPromotionWrapper carPromotionWrapper = new CarPromotionWrapper();
            if (PromotionType.Ordinary.equals(item.getSalesType())) {
                if (CollectionUtils.isNotEmpty(packList)) {
                    for (YgProductPack pack : packList) {
                        List<String> packProductIdList = Arrays.asList(pack.getProductIds().split(","));
                        if (packProductIdList.contains(item.getProductId().toString())) {
                            item.setSalesType(PromotionType.Pack);
                            carPromotionWrapper.setPromotionId(pack.getId());
                            carPromotionWrapper.setProductPack(pack);
                            break;
                        }
                    }
                }
            }
            //多买多折优惠
            if (PromotionType.Ordinary.equals(item.getSalesType())) {
                List<BmdismLadderModel> ladderModelList = ygBmdismService.findBmdismListWithLadderByProductIds(item.getProductId());
                if (CollectionUtils.isNotEmpty(ladderModelList)) {
                    BmdismLadderModel bmdismLadderModel = ladderModelList.get(0);
                    item.setSalesType(PromotionType.Bmdism);
                    carPromotionWrapper.setPromotionId(bmdismLadderModel.getId());
                    carPromotionWrapper.setBmdism(bmdismLadderModel);
                }
            }
            if (PromotionType.ManZeng.equals(item.getSalesType())) {
                //这里逻辑不够严谨
                SalesPlatform salesPlatform = PlatformUtil.converte(platformNo);
                List<YgPromotion> manzeng = ygPromotionService.findPromotionBySkuId(item.getSkuId(), PromotionType.ManZeng, null, salesPlatform);
                BigDecimal limitPrice;
                if (CollectionUtils.isEmpty(manzeng)) {
                    limitPrice = ygProductActionGiftService.getSalePriceOfActionProduct(item.getProductId());
                } else {
                    limitPrice = manzeng.get(0).getLimitPrice();
                }
                carPromotionWrapper.setLimitPrice(limitPrice);
            }
            carPromotionWrapper.setCarBasicData(item);

            carPromotionWrapperList.add(carPromotionWrapper);
//            //新客价
//            if (PromotionType.Ordinary.equals(item.getSalesType()) && item.getNewCustomPrice().compareTo(BigDecimal.ZERO) > 0 && isNewCustoms) {
//                item.setSalesType(PromotionType.NewCustom);
//            }
        });
        return carPromotionWrapperList;
    }

    /**
     * 设置满足促销的购物车标记、取消掉不满足的
     *
     * @param carList
     */
    private void setMeetPromotionTag(List<CarPromotionWrapper> carList, Boolean vip, Boolean newCustoms, Boolean distribution) {
        Map<PromotionType, List<CarPromotionWrapper>> promotionTypeListMap
                = carList.stream().collect(Collectors.groupingBy(carPromotionWrapper -> carPromotionWrapper.getCarBasicData().getSalesType()));

        for (Map.Entry<PromotionType, List<CarPromotionWrapper>> listEntry : promotionTypeListMap.entrySet()) {
            PromotionType key = listEntry.getKey();
            List<CarPromotionWrapper> value = listEntry.getValue();
            if (PromotionType.Pack.equals(key)) {
                Map<Long, List<CarPromotionWrapper>> collect = value.stream().collect(Collectors.groupingBy(CarPromotionWrapper::getPromotionId));
                for (Map.Entry<Long, List<CarPromotionWrapper>> entry : collect.entrySet()) {
                    setPackAmountByEachPackGroup(entry.getValue(), vip, distribution, newCustoms);
                }
            } else if (PromotionType.Bmdism.equals(key)) {
                setBestBmdismLadder(value, newCustoms);
            }
        }

    }

    private BmdismLadderModel.BmdismLadder getBestBmdismLadder(List<BmdismLadderModel.BmdismLadder> ladderList, Long buyCount) {
        BmdismLadderModel.BmdismLadder ladder = null;
        for (BmdismLadderModel.BmdismLadder m : ladderList) {
            if (buyCount >= m.getBuyCount()) {
                ladder = m;
            }
        }
        return ladder;
    }

    /**
     * 设置最优多买多折阶梯
     *
     * @param carList 购物车
     */
    private void setBestBmdismLadder(List<CarPromotionWrapper> carList, Boolean newCustoms) {

        Map<Long, List<CarPromotionWrapper>> bmdismMap =
                carList.stream().filter(carPromotionWrapper -> PromotionType.Bmdism.equals(carPromotionWrapper.getCarBasicData().getSalesType()))
                        .collect(Collectors.groupingBy(CarPromotionWrapper::getPromotionId));

        for (Map.Entry<Long, List<CarPromotionWrapper>> entry : bmdismMap.entrySet()) {
            BmdismLadderModel bmdism = entry.getValue().get(0).getBmdism();
            Long buyCount = entry.getValue().stream().map(carPromotionWrapper -> carPromotionWrapper.getCarBasicData().getQuantity())
                    .reduce(0L, (a, b) -> a + b);
            BmdismLadderModel.BmdismLadder bestBmdismLadder = getBestBmdismLadder(bmdism.getLadderList(), buyCount);
            entry.getValue().forEach(carPromotionWrapper -> {
                if (bestBmdismLadder != null) {
                    carPromotionWrapper.setBestLadder(bestBmdismLadder);
                } else {
                    carPromotionWrapper.getCarBasicData().setSalesType(PromotionType.Ordinary);
                    carPromotionWrapper.setPromotionId(null);
                    carPromotionWrapper.setBmdism(null);
                }
            });
        }
    }

    /**
     * 按真实销售价倒叙
     *
     * @param carList 购物车列表
     */
    private List<ShoppingCarBasicData> sortByRealSalesPriceDesc(List<ShoppingCarBasicData> carList) {
        //获取所有自选包商品并按价格倒序排列
        return carList.stream().sorted(Comparator.comparing(ShoppingCarBasicData::getRealSalesPrice).reversed()).collect(Collectors.toList());

    }

    private List<ShoppingCarBasicData> sortBySalesPriceDesc(List<ShoppingCarBasicData> carList) {
        //获取所有自选包商品并按价格倒序排列
        return carList.stream().sorted(Comparator.comparing(ShoppingCarBasicData::getSalesPrice).reversed()).collect(Collectors.toList());
    }

    /**
     * 将每个自选包分组的购物车商品 设置参与自选包的数量
     *
     * @param list 每个自选包分组
     */
    private void setPackAmountByEachPackGroup(List<CarPromotionWrapper> list, Boolean vip, Boolean distribution, Boolean newCustoms) {
        YgProductPack productPack = list.get(0).getProductPack();
        Map<Long, Long> carPackAmountMap = getCarPackAmountMap(list);
        //满足自选包商品平均售价
        BigDecimal packPrice = productPack.getPackPrice();
        if (vip) {
            packPrice = productPack.getPackVipPrice();
        }
        if (distribution) {
            packPrice = productPack.getPackDistributionPrice();
        }

        BigDecimal sharePrice = packPrice.divide(new BigDecimal(productPack.getProductAmount()), 2, BigDecimal.ROUND_DOWN);
        Long totalAmount = carPackAmountMap.values().stream().reduce(0L, (a, b) -> a + b);
        long cumulativeCount = totalAmount / productPack.getProductAmount();
        BigDecimal totalPackPrice = packPrice.multiply(new BigDecimal(cumulativeCount));

        Long lastAmount = totalAmount;
        BigDecimal lastPackPrice = totalPackPrice;
        for (CarPromotionWrapper carPromotionWrapper : list) {
            ShoppingCarBasicData carBasicData = carPromotionWrapper.getCarBasicData();
            Long packAmount = carPackAmountMap.get(carBasicData.getCarId());
            if (packAmount != null) {
                lastAmount = lastAmount - packAmount;
                if (lastAmount <= 0) {
                    carPromotionWrapper.setPackPrice(lastPackPrice);
                } else {
                    BigDecimal multiply = sharePrice.multiply(new BigDecimal(packAmount));
                    lastPackPrice = lastPackPrice.subtract(multiply);
                    carPromotionWrapper.setPackPrice(multiply);
                }
                carPromotionWrapper.setPackAmount(packAmount);
            } else {
                carBasicData.setSalesType(PromotionType.Ordinary);
                carPromotionWrapper.setPromotionId(null);
                carPromotionWrapper.setProductPack(null);
            }
        }
    }

    /**
     * 获取当前自选包分组的购物车商品参与自选包的数量
     *
     * @param list
     * @return key: 购物车id  value：参与数量
     */
    private Map<Long, Long> getCarPackAmountMap(List<CarPromotionWrapper> list) {
        //存放满足自选包活动的购物车id
        Map<Long, Long> packCarIdMap = new HashMap<>(list.size());
        YgProductPack productPack = list.get(0).getProductPack();
        Long productAmount = productPack.getProductAmount();
        Boolean cumulative = productPack.getCumulative();

        //累计次数
        Long cumulativeCount = 1L;
        Long buyCount = list.stream().map(carPromotionWrapper -> carPromotionWrapper.getCarBasicData().getQuantity()).reduce(0L, (a, b) -> a + b);
        if (cumulative) {
            cumulativeCount = buyCount / productAmount;
        } else if (buyCount.compareTo(productAmount) < 0) {
            cumulativeCount = 0L;
        }
        Long count = cumulativeCount * productAmount;
        if (count == 0) {
            return packCarIdMap;
        }
        BigDecimal totalPackPrice = productPack.getPackPrice().multiply(new BigDecimal(cumulativeCount));
        BigDecimal totalProductPrice = list.stream().map(car -> car.getCarBasicData().getSalesPrice()
                .multiply(new BigDecimal(car.getCarBasicData().getQuantity()))).reduce(BigDecimal.ZERO, BigDecimal::add);
        if (totalPackPrice.compareTo(totalProductPrice) >= 0) {
            return packCarIdMap;
        }

        Long lastCount = count;
        for (CarPromotionWrapper carPromotionWrapper : list) {
            ShoppingCarBasicData carBasicData = carPromotionWrapper.getCarBasicData();
            Long quantity = carBasicData.getQuantity();
            Long carId = carBasicData.getCarId();

            long tempCount = lastCount - quantity;
            if (tempCount >= 0) {
                packCarIdMap.put(carId, quantity);
            } else {
                packCarIdMap.put(carId, lastCount);
            }
            lastCount = tempCount;
            if (lastCount <= 0) {
                break;
            }
        }
        return packCarIdMap;
    }

    /**
     * 将所有自选包商品（按数量一一拆分）放到一个桶里，
     *
     * @param list 购物车自选包商品
     * @return List<CarPromotionWrapper>
     */
    private List<CarPromotionWrapper> setPackCarToBucket(List<CarPromotionWrapper> list) {
        List<CarPromotionWrapper> packSpitCarList = new ArrayList<>();
        for (CarPromotionWrapper car : list) {
            for (long i = 0; i < car.getCarBasicData().getQuantity(); i++) {
                CarPromotionWrapper clone = car.clone();
                clone.getCarBasicData().setQuantity(1L);
                packSpitCarList.add(clone);
            }
        }
        return packSpitCarList;
    }

    /**
     * 获取当前自选包分组的购物车商品参与自选包的数量（基于桶）
     *
     * @param list
     * @return key: 购物车id  value：参与数量
     */
    private Map<Long, Long> getCarPackAmountMapByBucket(List<CarPromotionWrapper> list) {
        YgProductPack productPack = list.get(0).getProductPack();
        //存放满足自选包活动的购物车id
        Map<Long, Long> packCarIdMap = new HashMap<>(list.size());
        Long productAmount = productPack.getProductAmount();
        Boolean useCoupon = productPack.getUseCoupon();
        Boolean cumulative = productPack.getCumulative();

        //累计次数
        Long cumulativeCount = 1L;
        if (cumulative) {
            cumulativeCount = list.size() / productAmount;
        } else if (list.size() < productAmount) {
            cumulativeCount = 0L;
        }
        Long count = cumulativeCount * productAmount;
        if (count == 0) {
            return packCarIdMap;
        }

        for (int i = 0; i < list.size(); i++) {
            ShoppingCarBasicData carBasicData = list.get(i).getCarBasicData();
            if (i < count) {
                Long quantity = packCarIdMap.get(carBasicData.getCarId());
                if (quantity == null) {
                    quantity = 0L;
                }
                quantity++;
                packCarIdMap.put(carBasicData.getCarId(), quantity);
            }
        }
        return packCarIdMap;
    }

    /**
     * 重置新客价
     * 同一花色下，多个尺码只用一件商品参与新客价 （将价格最高的设置为新客价）
     *
     * @param carList 购物车列表
     */
    public void resetNewCustomPrice(List<ShoppingCarBasicData> carList) {
        carList = sortBySalesPriceDesc(carList);
        Map<Long, List<ShoppingCarBasicData>> collect = carList.stream().filter(carBasicData ->
                carBasicData.getNewCustomPrice().compareTo(new BigDecimal(0)) > 0).collect
                (Collectors.groupingBy(ShoppingCarBasicData::getProductId));
        collect.forEach((k, v) -> {
            v.sort(Comparator.comparing(ShoppingCarBasicData::getSalesPrice).reversed());
            int[] idx = {0};
            v.forEach(car -> {
                if (idx[0] > 0) {
                    car.setNewCustomPrice(BigDecimal.ZERO);
                }
                idx[0]++;
            });
        });

    }

}
